package com.neuedu.wemall.member.controller;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.neuedu.wemall.common.util.FileUtils;
import com.neuedu.wemall.common.util.SignUtils;
import com.neuedu.wemall.common.util.StringUtils;
import com.neuedu.wemall.common.vo.ResponseData;
import com.neuedu.wemall.dao.entity.Member;
import com.neuedu.wemall.service.IMemberService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

/**
 * Author lu
 * Date   2025-09-08 15:17:25
 */
@Log4j2
@RequestMapping("/wemall/member/api")
@RestController
@Tag(name = "会员用户控制器")
public class MemberController extends BaseController {

    @Autowired
    @Qualifier("memberService")
    private IMemberService memberService;
    //令牌失效时间
    @Value("${config.token.expire}")
    private int expire;

    /**
     * 上传图片文件所存放的服务器本地目录
     */
    @Value("${file.upload.img.location}")
    private String imgLocationPath;
    /**
     * 上传图片文件URL前缀
     */
    @Value("${file.upload.img.prefix}")
    private String imgUrlPrefix;

    /**
     * 发送注册验证码
     *
     * @param email
     * @return
     */
    @PostMapping("/send_register_code")
    @Operation(summary = "发送注册验证码")
    @Parameters({
            @Parameter(name = "email", description = "邮箱", required = true)
    })
    public ResponseData sendRegisterCode(@RequestParam("email") String email) {
        return memberService.sendRegisterCode(email);
    }

    /**
     * 发送找回密码验证码
     *
     * @param email 注册邮箱
     * @return
     */
    @PostMapping("/send_find_password_code")
    @Operation(summary = "发送找回密码验证码")
    @Parameters({
            @Parameter(name = "email", description = "注册邮箱", required = true)
    })
    public ResponseData sendFindPasswordCode(@RequestParam("email") String email) {
        if (getRedis().hasKey(getLoginKey(email))) {
            return ResponseData.fail(999, "该邮箱已登录,不可以找回密码");
        }
        return memberService.sendFindPasswordCode(email);
    }

    /**
     * 会员注册
     *
     * @param email      邮箱
     * @param emailCode  邮箱验证码
     * @param password   密码
     * @param confirmPwd 确认密码
     * @return
     */
    @PostMapping("/register")
    @Operation(summary = "会员注册")
    public ResponseData register(@RequestParam(name = "email", required = true) @Parameter(name = "email", description = "邮箱", required = true) String email,
                                 @RequestParam(name = "emailCode", required = true) @Parameter(name = "emailCode", description = "邮箱验证码", required = true) String emailCode,
                                 @RequestParam(name = "password", required = true) @Parameter(name = "password", description = "密码", required = true) String password,
                                 @RequestParam(name = "confirmPwd", required = true) @Parameter(name = "confirmPwd", description = "确认密码", required = true) String confirmPwd) {
        if (StrUtil.isEmpty(email)) {
            return ResponseData.missParam("邮箱");
        }
        if (StrUtil.isEmpty(emailCode)) {
            return ResponseData.missParam("邮箱验证码");
        }
        if (StrUtil.isEmpty(password)) {
            return ResponseData.missParam("密码");
        }
        if (StrUtil.isEmpty(confirmPwd)) {
            return ResponseData.missParam("确认密码");
        }
        if (!password.equals(confirmPwd)) {
            return ResponseData.missParam("两次密码不一致");
        }
        //调用业务方法进行注册
        return memberService.register(email, emailCode, password);
    }

    /**
     * 重置密码
     *
     * @param email      邮箱
     * @param emailCode  邮箱验证码
     * @param password   密码
     * @param confirmPwd 确认密码
     * @return
     */
    @PostMapping("/reset")
    @Operation(summary = "重置密码")
    public ResponseData resetPassword(@RequestParam(name = "email", required = true) @Parameter(name = "email", description = "邮箱", required = true) String email,
                                      @RequestParam(name = "emailCode", required = true) @Parameter(name = "emailCode", description = "邮箱验证码", required = true) String emailCode,
                                      @RequestParam(name = "password", required = true) @Parameter(name = "password", description = "密码", required = true) String password,
                                      @RequestParam(name = "confirmPwd", required = true) @Parameter(name = "confirmPwd", description = "确认密码", required = true) String confirmPwd) {
        if (StrUtil.isEmpty(email)) {
            return ResponseData.missParam("邮箱");
        }
        if (StrUtil.isEmpty(emailCode)) {
            return ResponseData.missParam("邮箱验证码");
        }
        if (StrUtil.isEmpty(password)) {
            return ResponseData.missParam("密码");
        }
        if (StrUtil.isEmpty(confirmPwd)) {
            return ResponseData.missParam("确认密码");
        }
        if (!password.equals(confirmPwd)) {
            return ResponseData.missParam("两次密码不一致");
        }
        return memberService.resetPassword(email, emailCode, password);
    }

    /**
     * 会员登录
     *
     * @param email    邮箱
     * @param password 密码
     * @return
     */
    @PostMapping("/login")
    @Operation(summary = "会员登录")
    public ResponseData login(@RequestParam(name = "email", required = true) @Parameter(name = "email", description = "邮箱", required = true) String email,
                              @RequestParam(name = "password", required = true) @Parameter(name = "password", description = "密码", required = true) String password) {
        if (StrUtil.isEmpty(email)) {
            return ResponseData.missParam("邮箱");
        }
        if (StrUtil.isEmpty(password)) {
            return ResponseData.missParam("密码");
        }
        if (getRedis().hasKey(getLoginKey(email))) {
            return ResponseData.fail(999, "该账号已登录,请不要重复登录");
        }
        //调用业务方法进行登录
        Member member = memberService.login(email, password);
        if (member == null) {
            return ResponseData.fail(999, "登录失败,密码错误");
        }
        int status = member.getStatus();
        if (3 == status) {
            return ResponseData.fail(999, "用户已被注销");
        }
        if (2 == status) {
            return ResponseData.fail(999, "用户已被禁用");
        }
        if (1 != status) {
            return ResponseData.fail(999, "用户状态异常");
        }
        //登录成功,给用户发通行证(令牌)token
        Integer userId = member.getId();
        String id = String.valueOf(userId);
        String randomStr = SignUtils.getNonceStr();
        String token = SignUtils.getToken(id, email, randomStr, getRequest());
        String signStr = SignUtils.getSignStr(id, email, randomStr, token);
        //将签名字符串存放到redis中
        getRedis().set(getTokenKey(token), signStr, expire);
        //将邮箱放到redis中
        getRedis().set(getLoginKey(email), email, expire);
        return ResponseData.success(token);
    }

    /**
     * 会员退出登录
     *
     * @return
     */
    @PostMapping("/logout")
    @Operation(summary = "会员退出系统")
    @Parameters({
            @Parameter(name = "token", description = "令牌", required = true)
    })
    public ResponseData logout() {
        int userId = getMemberUserID();
        Member member = memberService.getById(userId);
        String email = member.getEmail();
        //删除用户数据
        getRedis().del(getTokenKey());
        getRedis().del(getLoginKey(email));
        return ResponseData.success("success");
    }

    /**
     * 修改密码
     *
     * @param oldPwd     旧密码
     * @param newPwd     新密码
     * @param confirmPwd 确认密码
     * @return
     */
    @PostMapping("/modify_pwd")
    @Operation(summary = "修改密码")
    @Parameters({@Parameter(name = "token", description = "令牌", required = true)})
    public ResponseData modifyPassword(
            @RequestParam(name = "oldPwd", required = true) @Parameter(name = "oldPwd", description = "旧密码", required = true) String oldPwd,
            @RequestParam(name = "newPwd", required = true) @Parameter(name = "newPwd", description = "密码", required = true) String newPwd,
            @RequestParam(name = "confirmPwd", required = true) @Parameter(name = "confirmPwd", description = "确认密码", required = true) String confirmPwd) {

        if (StrUtil.isEmpty(oldPwd)) {
            return ResponseData.missParam("旧密码");
        }
        if (StrUtil.isEmpty(newPwd)) {
            return ResponseData.missParam("新密码");
        }
        if (StrUtil.isEmpty(confirmPwd)) {
            return ResponseData.missParam("确认密码");
        }
        int userId = getMemberUserID();
        ResponseData responseData = memberService.updatePassword(userId, oldPwd, newPwd, confirmPwd);
        if (200 == responseData.getCode()) {
            //删除用户数据
            Member member = memberService.getById(userId);
            String email = member.getEmail();
            getRedis().del(getLoginKey(email));
            getRedis().del(getTokenKey());
        }
        return responseData;
    }

    /**
     * 查询会员用户信息
     *
     * @return
     */
    @GetMapping("/info")
    @Operation(summary = "查询会员用户基本信息")
    @Parameters({
            @Parameter(name = "token", description = "令牌", required = true)
    })
    public ResponseData personalInfo() {
        int userId = getMemberUserID();
        Member member = memberService.getById(userId);
        return ResponseData.success(member);
    }

    /**
     * 修改基本信息
     *
     * @param member
     * @return
     */
    @PostMapping("modify")
    @Operation(summary = "修改会员基本信息")
    @Parameters({
            @Parameter(name = "token", description = "令牌", required = true, schema = @Schema(type = "string")),
            @Parameter(name = "username", description = "账号", required = false, schema = @Schema(type = "string")),
            @Parameter(name = "mobile", description = "手机号", required = false, schema = @Schema(type = "string")),
            @Parameter(name = "gender", description = "性别(1:男;2:女)", required = false, schema = @Schema(type = "integer")),
            @Parameter(name = "birth", description = "出生日期", required = false, schema = @Schema(type = "date")),
            @Parameter(name = "nickname", description = "昵称", required = false, schema = @Schema(type = "string")),
            @Parameter(name = "city", description = "所在城市", required = false, schema = @Schema(type = "string")),
            @Parameter(name = "idCard", description = "身份证号", required = false, schema = @Schema(type = "string"))
    })
    public ResponseData modifyBaseInfo(@Parameter(hidden = true)Member member) {
        int userId = getMemberUserID();
        member.setId(userId);
        return memberService.modifyById(member);
    }

    /**
     * 设置会员头像
     *
     * @param avatarFile
     * @return
     */
    @PostMapping("/set_avatar")
    @Operation(summary = "设置会员头像")
    @Parameters({
            @Parameter(name = "token", description = "令牌", required = true, schema = @Schema(type = "string")),
            @Parameter(name = "avatar", description = "会员用户头像", required = true, schema = @Schema(type = "file"))
    })
    public ResponseData setAvatar(@RequestParam(value = "avatar", required = true) @Parameter(hidden = true) MultipartFile avatarFile) {
        int userId = getMemberUserID();
        if (avatarFile.isEmpty()) {
            ResponseData.fail(999, "上传失败,未上传任何头像图片文件");
        }
        //原始文件名称
        String originFileName = avatarFile.getOriginalFilename();
        if (originFileName == null) {
            return ResponseData.fail(999, "无法获取文件名");
        }
        //文本扩展名
        String suffix = originFileName.substring(originFileName.lastIndexOf('.'));
        if (!FileUtils.isImgFile(originFileName)) {
            return ResponseData.fail(999, "头像文件格式错误,请选择图片文件");
        }
        String newFileName = StringUtils.getUUID32() + suffix;
        log.info(newFileName);
        //上传文件所在父目录,head+用户ID
        String parentName = "head/" + userId;
        File parent = new File(imgLocationPath, parentName);
        FileUtil.mkParentDirs(parent);
        FileUtil.mkdir(parent);
        File dest = new File(parent, newFileName);
        try {
            avatarFile.transferTo(dest);
            int maxSize = 400 * 1024;
            int maxWidth = 400;
            int maxHeight = 400;
            boolean correct = FileUtils.checkImgStyle(maxSize, maxWidth, maxHeight, dest.getPath());
            if (!correct) {
                dest.delete();
                return ResponseData.fail(999, "上传图片大小不能超过400KB,尺寸不能超过400*400");
            }
            //图片URL
            String imgUrl = imgUrlPrefix.replace("**", "") + parentName + '/' + newFileName;
            //更新会员头像
            Member member = new Member();
            member.setId(userId);
            member.setAvatar(imgUrl);
            boolean result = memberService.updateById(member);
            if (result) {
                return ResponseData.success(imgUrl);
            }
            return ResponseData.fail(999, "设置头像失败,用户不存在");
        } catch (IOException e) {
            log.error(e.toString(), e);
            return ResponseData.fail(500, e.toString());
        }
    }

}